﻿// =============================================
// 文件保护宏：防止该头文件（或 Pass 代码）被重复包含
// 如果尚未定义 CUSTOM_UNLIT_PASS_INCLUDED，则定义它并继续，否则跳过该部分代码的编译
// =============================================
#ifndef CUSTOM_UNLIT_PASS_INCLUDED
#define CUSTOM_UNLIT_PASS_INCLUDED

// =============================================
// 引入自定义的通用 Shader 函数与工具库
// 通常包括：数学函数、坐标变换函数（如 TransformObjectToWorld、TransformWorldToHClip）、常用语义等
// 这是你项目 ShaderLibrary 中的 Common.hlsl，类似于 Unity URP 中的 Core.hlsl
// =============================================
#include "../ShaderLibrary/Common.hlsl"

// =============================================
// 声明一个 2D 纹理资源，名称为 _BaseMap
// 通常是物体的基础贴图（比如 Diffuse / Albedo 贴图），用于提供物体表面的颜色信息
// =============================================
TEXTURE2D(_BaseMap);

// =============================================
// 声明一个采样器（SamplerState），名称为 sampler_BaseMap
// 用于定义如何从 _BaseMap 贴图中采样颜色（比如过滤方式、Wrap 模式等）
// 在 Unity SRP 中，推荐将纹理和采样器分开声明，以获得更大的灵活性和优化空间
// =============================================
SAMPLER(sampler_BaseMap);

// =============================================
// 定义一个 Unity Instancing 材质属性缓冲区，名称为 UnityPerMaterial
// 用于存储每个物体（或材质实例）可定制的属性，支持 GPU Instancing 批处理
// 下面定义了三个属性，都是 "INSTANCED"，即每个物体可以有不同的值
// =============================================
UNITY_INSTANCING_BUFFER_START(UnityPerMaterial)

	// _BaseMap_ST：贴图的 Tiling（缩放）和 Offset（偏移）参数，float4 格式：(x=scaleX, y=scaleY, z=offsetX, w=offsetY)
	// 用于控制贴图在物体表面的平铺和位移效果
	UNITY_DEFINE_INSTANCED_PROP(float4, _BaseMap_ST)

	// _BaseColor：基础颜色（RGBA），用于与贴图相乘，决定物体最终的颜色表现
	UNITY_DEFINE_INSTANCED_PROP(float4, _BaseColor)

	// _Cutoff：Alpha 裁剪阈值，范围 [0, 1]，用于控制透明像素的剔除（仅当启用 _CLIPPING 时生效）
	UNITY_DEFINE_INSTANCED_PROP(float, _Cutoff)

// =============================================
// 结束 Unity Instancing 材质属性缓冲区的定义
// =============================================
UNITY_INSTANCING_BUFFER_END(UnityPerMaterial)

// =============================================
// 定义顶点着色器的输入结构体：Attributes
// 包括：物体空间中的顶点位置、第一组 UV 坐标、以及 Instancing 实例 ID
// =============================================
struct Attributes {
	float3 positionOS : POSITION;      // 顶点在物体本地空间（Object Space）中的位置
	float2 baseUV : TEXCOORD0;         // 第一套 UV 坐标，通常用于贴图采样
	UNITY_VERTEX_INPUT_INSTANCE_ID     // 声明该结构体包含一个 Instancing 实例 ID，用于区分不同物体
};

// =============================================
// 定义顶点着色器的输出 / 片段着色器的输入结构体：Varyings
// 包括：裁剪空间中的顶点位置、变换后的 UV 坐标、以及 Instancing 实例 ID
// =============================================
struct Varyings {
	float4 positionCS : SV_POSITION;   // 顶点在裁剪空间（Clip Space）中的位置，用于屏幕映射和光栅化
	float2 baseUV : VAR_BASE_UV;       // 传递到片段着色器的 UV 坐标，用于贴图采样
	UNITY_VERTEX_INPUT_INSTANCE_ID     // 传递 Instancing 实例 ID 到片段着色器
};

// =============================================
// 顶点着色器入口函数：UnlitPassVertex
// 功能：将顶点从物体空间变换到裁剪空间，并处理 UV 坐标变换
// =============================================
Varyings UnlitPassVertex(Attributes input) {
	Varyings output;
	UNITY_SETUP_INSTANCE_ID(input);               // 初始化当前实例的 ID，必须在访问 Instanced 属性前调用
	UNITY_TRANSFER_INSTANCE_ID(input, output);    // 将当前实例的 ID 从顶点传递到片段着色器

	// 将顶点位置从物体本地空间（Object Space）转换到世界空间（World Space）
	float3 positionWS = TransformObjectToWorld(input.positionOS);

	// 将世界空间坐标转换到裁剪空间（Clip Space），即应用 MVP 变换的最终阶段
	// 这是顶点着色器的最终输出，用于后续的光栅化和屏幕映射
	output.positionCS = TransformWorldToHClip(positionWS);

	// 从 Instancing 缓冲区中获取当前物体的 _BaseMap_ST（贴图 Tiling 和 Offset）
	float4 baseST = UNITY_ACCESS_INSTANCED_PROP(UnityPerMaterial, _BaseMap_ST);

	// 对原始 UV 坐标应用 Tiling (xy) 和 Offset (zw)，计算最终 UV，用于贴图采样
	output.baseUV = input.baseUV * baseST.xy + baseST.zw;

	return output;
}

// =============================================
// 片段着色器入口函数：UnlitPassFragment
// 功能：采样贴图、应用基础颜色、执行 Alpha 裁剪（如果启用）
// 返回值：float4(color, alpha)，即最终渲染到屏幕的颜色
// =============================================
float4 UnlitPassFragment(Varyings input) : SV_TARGET {
	UNITY_SETUP_INSTANCE_ID(input); // 初始化当前实例 ID，访问 Instanced 属性前必须调用

	// 从 _BaseMap 贴图中采样颜色，使用当前 UV 和采样器
	float4 baseMap = SAMPLE_TEXTURE2D(_BaseMap, sampler_BaseMap, input.baseUV);

	// 从 Instancing 缓冲区中获取当前物体的基础颜色 _BaseColor
	float4 baseColor = UNITY_ACCESS_INSTANCED_PROP(UnityPerMaterial, _BaseColor);

	// 计算最终的基础颜色：贴图颜色 × 基础颜色
	float4 base = baseMap * baseColor;

	// 如果定义了 _CLIPPING 宏（通常由 Shader Feature 或材质开关控制）
	#if defined(_CLIPPING)
		// 如果当前像素的 Alpha 值 < _Cutoff，则 discard（不渲染该像素）
		// 用于实现硬边缘透明效果，比如铁丝网、叶片等
		clip(base.a - UNITY_ACCESS_INSTANCED_PROP(UnityPerMaterial, _Cutoff));
	#endif

	// 返回最终颜色到渲染目标（比如屏幕或 RenderTexture）
	return base;
}

// =============================================
// 文件保护宏结束
// =============================================
#endif